from flask import jsonify, request
from flask_restful import Resource
from flask_restful import reqparse
from werkzeug.security import generate_password_hash,check_password_hash
from werkzeug.utils import secure_filename
from extensions import db
from datetime import datetime
from data_models import Account,Notice,Profile,Comment
import os
from sqlalchemy.exc import SQLAlchemyError
from flask_jwt_extended import create_access_token, jwt_required, get_jwt_identity,get_jwt
from sqlalchemy import func
import json
from flask import current_app
import mimetypes

#对应vue后端的用户管理部分，获取数据和添加数据
class MemberManage(Resource):
    @jwt_required()
    def post(self):
        # token
        # identity = get_jwt_identity()
        claims = get_jwt()     
        if claims.get("role") != "admin":
            return {
                "code":402,
                "msg": "无权限",     
            },403
        # 1. 定义参数解析
        parser = reqparse.RequestParser()
        parser.add_argument("student_id", type=str, required=True, help="学号不能为空")
        parser.add_argument("password", type=str, required=True, help="密码不能为空")
        args = parser.parse_args()
        
        
        # 2. 检查 student_id 是否已存在
        existing = Account.query.filter_by(student_id=args["student_id"]).first()
        if existing:
            return {"code": 400, "msg": "该学号已注册"}, 400
        
        
        # 3. 生成密码哈希
        hashed_pw = generate_password_hash(args["password"])
        
        
        # 4. 创建 Account 实例
        userdata = Account(
            student_id=args["student_id"],
            password_hash=hashed_pw,
            created_at=datetime.utcnow()
        )

        
        # 5. 写入数据库
        db.session.add(userdata)
        db.session.commit()

        # 6. 返回结果
        return {
            "code": 200,
            "msg": "注册成功",
            "data": {
                "id": userdata.id,
                "student_id": userdata.student_id,
                "created_at": userdata.created_at.isoformat()
            }
        }, 201
    
    def get(self):
        # 查询所有用户 除管理员
        accounts = Account.query.filter(Account.role != "admin").all()

        # 组织返回结果
        data = []
        for acc in accounts:
            if acc.profile:  # 有 profile 才组织数据
                data.append({
                    "student_id": acc.student_id,
                    "full_name": acc.profile.full_name,
                    "phone": acc.profile.phone ,
                    "graduation_year": acc.profile.graduation_date,
                    "degree": acc.profile.degree,
                    "workplace": acc.profile.workplace,
                    "acad_status": acc.profile.acad_status,
                    
                    
    
                })
            else:
                data.append({
                    "student_id": acc.student_id,
                    "full_name": "未填写",
                    "phone": "未填写",
                    "graduation_year": "未填写",
                    "acad_status": "未填写",
                    "degree": "未填写",
                    "workplace": "未填写",
                    
            
                })
                
        return {
            "code": 200,
            "msg": "获取成功",
            "data": data
        }, 200
        
        
        
#登录的请求
class LoginAPI(Resource):
    def post(self):
        parser = reqparse.RequestParser()
        parser.add_argument("student_id", type=str, required=True, help="学号不能为空")
        parser.add_argument("password", type=str, required=True, help="密码不能为空")
        args = parser.parse_args()

        # 1. 查询用户
        user = Account.query.filter_by(student_id=args["student_id"]).first()
        if not user:
            return {"code": 404, "msg": "用户不存在"}, 404

        # 2. 校验密码
        if not check_password_hash(user.password_hash, args["password"]):
            return {"code": 401, "msg": "密码错误"}, 401

        # 生成 JWT
        # token = create_access_token(
        #     identity={"id": user.id, "student_id": user.student_id, "role": user.role}
        #     )
        token = create_access_token(
        identity=str(user.id),
        additional_claims={
            "student_id": user.student_id,
            "role": user.role
        }
    )

        # 3. 登录成功，返回用户信息（不要返回密码哈希）
        return {
            "code": 200,
            "msg": "登录成功",
            "data": {
                "token": token,
                "id": user.id,
                "student_id": user.student_id,
                "role": user.role,
                "created_at": user.created_at.isoformat()  
            }
        }, 200
        
        
#发布notice的界面 管理员界面
class NoticeAPI(Resource):
    @jwt_required()
    def post(self):
        data = request.get_json(force=True)  # ✅ 直接解析 JSON 请求体
        title = data.get("title")
        contact = data.get("contact")
        summary = data.get("summary")
        content = data.get("content")
        images = data.get("images", [])  # ✅ 直接拿到 list 类型

        if not title:
            return {"code": 400, "msg": "发布标题不能为空"}, 400

        # 这里 images 仍是一个 list，如 ["url1", "url2"]
        # 存数据库前用 json.dumps 转成字符串
       
        images_json = json.dumps(images)

        notice = Notice(
            title=title,
            contact=contact,
            summary=summary,
            content=content,
            images=images_json,
            account_id=get_jwt_identity(),
        )
        db.session.add(notice)
        db.session.commit()
        return {"code": 200, "msg": "通知创建成功", "id": notice.id}, 200
    #首页获取notices信息的页面
    def get(self):
        notices = Notice.query.order_by(Notice.created_at.desc()).all()
        data = [
            {
                "id": n.id,
                "title": n.title,
                "contact": n.contact,
                "summary": n.summary,
                "content": n.content,
                "created_at": n.created_at.isoformat(),
                # "student_id":n.author.student_id,
            }
            for n in notices
        ]

        return {"code": 200, "msg": "获取成功", "data": data}, 200


# 添加评论
class CommentAPI(Resource):
    @jwt_required()
    def post(self, notice_id):
        account_id = get_jwt_identity()
        parser = reqparse.RequestParser()
        parser.add_argument("content", type=str, required=True, help="评论内容不能为空")
        args = parser.parse_args()
        comment = Comment(
            content=args["content"],
            notice_id=notice_id,
            account_id=account_id
        )
        db.session.add(comment)
        db.session.commit()

        return {"code": 200, "msg": "评论添加成功", "id": comment.id}, 201

    
#获得单个通知的详细内容
class NoticeDetailAPI(Resource):
    def get(self, notice_id):
        notice = Notice.query.get(notice_id)
        if not notice:
            return {"code": 404, "msg": "通知不存在"}, 404

        return {
            "code": 200,
            "msg": "获取成功",
            "data": {
                "id": notice.id,
                "title": notice.title,
                "contact": notice.contact,
                "summary": notice.summary,
                "content": notice.content,
                "created_at": notice.created_at.isoformat(),
                "student_id":notice.author.student_id,
                "images":notice.images,
            }
        }, 200

# 获取某个 Notice 的所有评论
class NoticeCommentsAPI(Resource):
    @jwt_required(optional=True)
    def get(self, notice_id):
        comments = Comment.query.filter_by(notice_id=notice_id).all()
        data = [
            {
                "id": c.id,
                "content": c.content,
                "created_at": c.created_at.isoformat(),
                "account_id": c.account_id
            }
            for c in comments
        ]
        return {"code": 200, "msg": "获取成功", "data": data}, 200



# 获取某个 student_id 的所有通知
class StudentNoticesAPI(Resource):
    @jwt_required()
    def get(self, student_id):
        notices = (
            Notice.query
            .join(Notice.author)  # 正确写法
            .filter(Account.student_id == student_id)
            .order_by(Notice.created_at.desc())  # 按时间倒序（最新在前）
            .all()
        )
        data = [
            {
                "id": n.id,
                "title": n.title,
                "summary": n.summary,
                "created_at": n.created_at.isoformat(),
                "content":n.content,
                "contact":n.contact,
                #"student_id": n.author.student_id,  # ✅ 可直接访问 author 属性？
            }
            for n in notices
        ]
        return {"code": 200, "msg": "获取成功", "data": data}, 200
    
    @jwt_required()
    def delete(self, notice_id):
        notice = Notice.query.get(notice_id)
        if not notice:
            return {"code": 404, "msg": "帖子不存在"}, 404

        # ✅ 1. 删除数据库前，先处理图片文件
        try:
            if notice.images:
                # images 字段是 JSON 字符串时
                image_list = json.loads(notice.images) if isinstance(notice.images, str) else notice.images
                
                for img_path in image_list:
                    # 拼接完整服务器文件路径
                    full_path = os.path.join(current_app.root_path, img_path.lstrip("/"))
                    
                    # ✅ 防御性判断：防止误删系统文件
                    if os.path.exists(full_path) and "static/notice_images" in full_path:
                        os.remove(full_path)
                        print(f"✅ 已删除图片: {full_path}")
        except Exception as e:
            print(f"⚠️ 删除图片失败: {e}")

        # ✅ 2. 删除数据库记录
        db.session.delete(notice)
        db.session.commit()

        return {"code": 200, "msg": "帖子及图片删除成功"}, 200

# 获取某个 student_id 的所有评论
class StudentCommentsAPI(Resource):
    @jwt_required()
    def get(self, student_id):
        comments = Comment.query.join("account").filter_by(student_id=student_id).all()
        data = [
            {
                "id": c.id,
                "content": c.content,
                "created_at": c.created_at.isoformat(),
                "notice_id": c.notice_id
            }
            for c in comments
        ]
        return {"code": 200, "msg": "获取成功", "data": data}, 200

#用户上传和修改信息
class ProfileAPI(Resource):
    def get(self, student_id):
        """根据 student_id 获取用户资料"""
        account = Account.query.filter_by(student_id=student_id).first()
        if not account:
            return {"code": 404, "msg": "账号不存在"}, 404

        if not account.profile:
            return {"code": 404, "msg": "用户资料不存在"}, 404

        profile = account.profile
        return {
            "code": 200,
            "msg": "获取成功",
            "data": {
                "student_id": account.student_id,
                "full_name": profile.full_name,
                "birth_date": profile.birth_date,
                "address": profile.address,
                "phone": profile.phone,
                "email": profile.email,
                "advisor": profile.advisor,
                "degree": profile.degree,
                "graduation_date": profile.graduation_date,
                "workplace": profile.workplace,
                "organization":profile.organization,
                "job_title": profile.job_title,
                "research_direction": profile.research_direction,
                "introduction": profile.introduction,
                "achievements": profile.achievements,
                "avatar_url": profile.avatar_url,
                "job_type": profile.job_type,
                "acad_status": profile.acad_status,
                "tag": profile.tag,
            }
        }, 200

    def post(self, student_id):
        """创建或更新用户资料"""
        parser = reqparse.RequestParser()
        parser.add_argument("full_name", type=str)
        parser.add_argument("birth_date", type=str)
        parser.add_argument("address", type=str)
        parser.add_argument("phone", type=str)
        parser.add_argument("email", type=str)
        parser.add_argument("advisor", type=str)
        parser.add_argument("degree", type=str)
        parser.add_argument("graduation_date", type=str)
        parser.add_argument("workplace", type=str)
        parser.add_argument("organization", type=str)
        parser.add_argument("job_title", type=str)
        parser.add_argument("research_direction", type=str)
        parser.add_argument("introduction", type=str)
        parser.add_argument("achievements", type=str)
        parser.add_argument("avatar_url", type=str)
        parser.add_argument("acad_status", type=str)
        parser.add_argument("job_type", type=str)
        parser.add_argument("tag", type=str)
        args = parser.parse_args()

        # 查找账号
        account = Account.query.filter_by(student_id=student_id).first()
        if not account:
            return {"code": 404, "msg": "账号不存在"}, 404

        profile = account.profile
        if not profile:
            profile = Profile(account_id=account.id, **args)
            db.session.add(profile)
        else:
            for key, value in args.items():
                if value is not None:
                    setattr(profile, key, value)

        db.session.commit()
        return {"code": 200, "msg": "保存成功"}, 200
    

#修改密码的api
class ChangePasswordAPI(Resource):
    @jwt_required()
    def post(self):
        parser = reqparse.RequestParser()
        parser.add_argument("student_id", type=str, required=True)
        parser.add_argument("old_password", type=str, required=True)
        parser.add_argument("new_password", type=str, required=True)
        args = parser.parse_args()

        user = Account.query.filter_by(student_id=args["student_id"]).first()
        if not user:
            return {"code": 404, "msg": "用户不存在"}, 404

        # 验证旧密码
        if not check_password_hash(user.password_hash, args["old_password"]):
            return {"code": 401, "msg": "原密码错误"}, 401

        # 更新密码
        user.password_hash = generate_password_hash(args["new_password"])
        db.session.commit()

        return {"code": 200, "msg": "密码修改成功"}, 200


# 上传头像的api

UPLOAD_FOLDER = "static/uploads"
ALLOWED_EXTENSIONS = {"png", "jpg", "jpeg","PNG","JPG"}

# 确保目录存在
os.makedirs(UPLOAD_FOLDER, exist_ok=True)

def allowed_file(filename):
    return "." in filename and filename.rsplit(".", 1)[1].lower() in ALLOWED_EXTENSIONS


class AvatarUploadAPI(Resource):
    def post(self, student_id):

        if "file" not in request.files:
            return {"code": 400, "msg": "没有文件"}, 400

        file = request.files["file"]
        if file.filename == "":
            return {"code": 400, "msg": "文件名不能为空"}, 400

        if file and allowed_file(file.filename):
            # 获取文件后缀
            ext = file.filename.rsplit(".", 1)[1].lower()
            # 用 student_id 作为文件名
            filename = f"{student_id}.{ext}"

            save_path = os.path.join(UPLOAD_FOLDER, filename)
            file.save(save_path)


            # 生成访问 URL（根据你的项目配置）
            avatar_url = f"/{UPLOAD_FOLDER}/{filename}"

            # 更新数据库
            account = Account.query.filter_by(student_id=student_id).first()
            if not account:
                return {"code": 404, "msg": "账号不存在"}, 404

            if not account.profile:
                profile = Profile(account_id=account.id, avatar_url=avatar_url)
                db.session.add(profile)
            else:
                account.profile.avatar_url = avatar_url

            db.session.commit()
            return {"code": 200, "msg": "上传成功", "avatar_url": avatar_url}, 200

        return {"code": 400, "msg": "文件类型不支持"}, 400
    

#上传notices图片的api

UPLOAD_FOLDER_notice = os.path.join("static", "notice_images")
os.makedirs(UPLOAD_FOLDER_notice, exist_ok=True)
class NoticeImageUploadAPI(Resource):
    def post(self):
        if "file" not in request.files:
            return {"code": 400, "msg": "没有文件"}, 400
        file = request.files["file"]

        if file.filename == "":
            return {"code": 400, "msg": "文件名为空"}, 400
        
        filename = secure_filename(file.filename)
       
        # ✅ 如果文件名里没有点（即没有扩展名），根据 MIME 类型补上
        if "." not in filename:
            mime_type = file.mimetype  # 例如 image/jpeg
            guessed_ext = mimetypes.guess_extension(mime_type)
            if guessed_ext:
                filename = f"upload_{int(datetime.now().timestamp())}{guessed_ext}"
            else:
                return {"code": 400, "msg": f"无法识别文件类型: {mime_type}"}, 400

        # ✅ 检查文件类型是否被允许
        if not allowed_file(filename):
            return {"code": 400, "msg": "文件类型不支持"}, 400

        # ✅ 提取扩展名
        file_extension = filename.rsplit(".", 1)[1].lower()

        # ✅ 加时间戳生成新文件名
        timestamp = datetime.now().strftime("%Y%m%d%H%M%S")
        new_filename = f"{os.path.splitext(filename)[0]}_{timestamp}.{file_extension}"

        # ✅ 保存文件
        os.makedirs(UPLOAD_FOLDER_notice, exist_ok=True)
        save_path = os.path.join(UPLOAD_FOLDER_notice, new_filename)
        file.save(save_path)

        # ✅ 返回前端可访问的 URL
        url = f"/static/notice_images/{new_filename}"
        return {"code": 200, "msg": "上传成功", "url": url}, 200








#根据名字获取成员详细内容  
class ProfileSearch(Resource):
     def post(self):

            data = request.get_json(silent=True) or {}
            full_name = (data.get("full_name") or "").strip()

            if not full_name:
                return {"error": "full_name is required"}, 400

            try:
                profile = db.session.query(Profile).filter_by(full_name=full_name).first()
                if not profile:
                    return {"error": "Profile not found"}, 404
                return {
                    "code": 200,
                    "msg": "获取成功",
                        "data": {
                        "full_name": profile.full_name,
                        "birth_date": profile.birth_date,
                        "address": profile.address,
                        "phone": profile.phone,
                        "email": profile.email,
                        "advisor": profile.advisor,
                        "degree": profile.degree,
                        "graduation_date": profile.graduation_date,
                        "workplace": profile.workplace,
                        "organization":profile.organization,
                        "job_title": profile.job_title,
                        "job_type": profile.job_type,
                        "acad_status":profile.acad_status,
                        "research_direction": profile.research_direction,
                        "introduction": profile.introduction,
                        "achievements": profile.achievements,
                        "avatar_url": profile.avatar_url,
                        "tag":profile.tag,
                        }
                 }, 200
            except SQLAlchemyError as e:
                db.session.rollback()
                return {"error": "Database error", "detail": str(e)}, 500


class ProfileList(Resource):
    def get(self):
        try:
            profiles = db.session.query(Profile).all()
            data = []
            for p in profiles:
                data.append({
                    "full_name": p.full_name,
                    # "birth_date": p.birth_date,
                    # "address": p.address,
                    "phone": p.phone,
                    # "email": p.email,
                    # "advisor": p.advisor,
                    "degree": p.degree,
                    # "graduation_date": p.graduation_date,
                    "workplace": p.workplace,
                    # "organization": p.organization,
                    # "job_title": p.job_title,
                    # "research_direction": p.research_direction,
                    "introduction": p.introduction,
                    # "achievements": p.achievements,
                    "acad_status":p.acad_status,
                    "avatar_url": p.avatar_url,
                    "tag":p.tag,
                })

            return {
                "code": 200,
                "msg": "获取成功",
                "data": data
            }, 200
        except Exception as e:
            return {"code": 500, "msg": "服务器错误", "data": str(e)}, 500
        
        

class ProfileStats(Resource):
    def get(self):
        # 1. 统计工作地点（省份）
        workplace_counts = (
            db.session.query(Profile.workplace, func.count(Profile.id))
            .group_by(Profile.workplace)
            .all()
        )
        workplace_data = [
            {"name": wp if wp else "未知", "value": count}
            for wp, count in workplace_counts
        ]

        # 2. 统计工作类别
        jobtype_counts = (
            db.session.query(Profile.job_type, func.count(Profile.id))
            .group_by(Profile.job_type)
            .all()
        )
        jobtype_data = [
            {"name": jt if jt else "未知", "value": count}
            for jt, count in jobtype_counts
        ]

        # 3. 返回统一的数据
        return jsonify({
            "workplace_data": workplace_data,
            "jobtype_data": jobtype_data
        })